CSS - module 29 - media queries

revision:


Content

Media queries allow to apply CSS styles depending on a device's general type. Syntax Targeting media types Targeting media features Creating complex media queries Syntax improvements in Level 4 Adding breakpoints Typical device breekpoints Media queries examples Best practices for writing media queries Mobile-first vs Desktop-first media queries Media query for desktop Media query for tablet


Media queries allow to apply CSS styles depending on a device's general type.

top

Media queries are used:

to conditionally apply styles with the CSS @media and @import at-rules.

to target specific media for the <style>, <link>, <source>, and other HTML elements with the "media= attribute".

to test and monitor media states using the "Window.matchMedia()" and "EventTarget.addEventListener()" methods.

Example : if the browser window is 600px or smaller, the background color will be lightblue:

            @media only screen and (max-width: 600px) {
                body {
                  background-color: lightblue;
                }
              }
        

When to use media queries:

responsive layouts : adjust the layout for different screen sizes (mobile, tablet, desktop).

example

            @media (max-width: 768px) {
                .sidebar { display: none; }
            }
        

orientation-specific styling: tailor designs for portrait vs. landscape modes (useful for tablets or mobile devices).

example

        @media (orientation: landscape) {
            .hero { height: 50vh; }
        }
    

high-resolution displays: serve sharper images or adjust spacing for Retina or high-DPI screens.

example

        @media (-webkit-min-device-pixel-ratio: 2), (min-resolution: 192dpi) {
            .logo { background-image: url([email protected]); }
        }
    

accessibility considerations: respect user preferences like reduced motion or color schemes.

example

        @media (prefers-reduced-motion: reduce) {
            * { animation-duration: 0.01ms !important; }
        }
    

Syntax

top

A media query is composed of an optional media type and any number of media feature expressions, which may optionally be combined in various ways using logical operators.
Media queries are case-insensitive.

        @media not | only mediatype and (expressions) {
            CSS-Code;
          }
    

Media types define the broad category of device for which the media query applies: "all", "print", "screen", "speech".

all : used for all media type devices.

print : used for printers.

screen : used for computer screens, tablets, smart-phones, etc.

speech : used for screenreaders that "reads" the page out loud.

The type is optional (assumed to be all) except when using the "not" or "only" logical operators.

Media features describe a specific characteristic of the user agent, output device, or environment:

any-hover, any-pointer, aspect-ratio, color, color-gamut, color-index, device-aspect-ratio (deprecated), device-height (deprecated), device-posture, device-width (deprecated), display-mode, dynamic-range, forced-colors, grid, height, hover, inverted-colors, monochrome, orientation, overflow-block, overflow-inline, pointer, prefers-color-scheme, prefers-contrast, prefers-reduced-motion, prefers-reduced-transparency, resolution, scripting, update, video-dynamic-range, width

Logical operators can be used to compose a complex media query: "not", "and", and "only". You can also combine multiple media queries into a single rule by separating them with commas.

A media query computes to true when the media type (if specified) matches the device on which a document is being displayed and all media feature expressions compute as true. Queries involving unknown media types are always false.


Targeting media types

top

Media types describe the general category of a given device. Although websites are commonly designed with screens in mind, you may want to create styles that target special devices such as "printers" or "audio-based screen readers".

For example, this CSS targets printers:

            @media print{
                /* - - */
            }
        

You can also target multiple devices.

For instance, this @media rule uses two media queries to target both screen and print devices:

            @media screen, print{
                /* - - */
            }
        


Targeting media features

top

Media features describe the specific characteristics of a given user agent, output device, or environment. For instance, you can apply specific styles to widescreen monitors, computers that use mice, or to devices that are being used in low-light conditions.

This example applies styles when the user's primary input mechanism (such as a mouse) can hover over elements:

            @media (hover: hover){
                /* - - */
            }
        

Many media features are range features, which means they can be prefixed with "min-" or "max-" to express "minimum condition" or "maximum condition" constraints.

For example, this CSS will apply styles only if your browser's viewport width is equal to or narrower than 1250px:

            @media (max-width: 1250px){
                /* - - */
            }
        

If you create a media feature query without specifying a value, the nested styles will be used as long as the feature's value is not zero (or none, in Level 4).

For example, this CSS will apply to any device with a color screen:

            @media (color){
                /* - - */
            }
        


Creating complex media queries

top

Creating a media query that depends on multiple conditions needs logical operators to come in: not, and, and only. Furthermore, multiple media queries can be combined into a comma-separated list. This allows to apply the same styles in different situations.

The "and" operator can combine multiple media features into a single media query.

The "not" operator negates a media query, basically reversing its normal meaning.

The "only" operator prevents older browsers from applying the styles.

Combining multiple types or features : The "and" keyword combines a media feature with a media type or other media features.

This example combines two media features to restrict styles to landscape-oriented devices with a width of at least 30vw:

            @media (min-width: 30em) and (orientation: landscape){
                /* - - */
            }
        

To limit the styles to devices with a screen, the media features can be chained to the screen media type:

            @media screen and (min-height: 30em) and (orientation: portrait){
                /* - - */
            }
        

Testing for multiple queries : a comma-separated list can be used to apply styles when the user's device matches any one of various media types, features, or states.

For instance, the following rule will apply its styles if the user's device has either a minimum height of 680px or is a screen device in portrait mode:

            @media (min-height: 680px), screen and (orientation: portrait) {
                /* … */
              }
        

Inverting a query's meaning : The "not" keyword inverts the meaning of an entire media query. It will only negate the specific media query it is applied to. (Thus, it will not apply to every media query in a comma-separated list of media queries.) The not keyword can't be used to negate an individual feature query, only an entire media query.

The not is evaluated last in the following query:

            @media not all and (monochrome) {
                    /* … */
            }
            meaning:
                @media not(all and (monochrome)) {
                    /* … */
                }
        


Syntax improvements in Level 4

top

The Media Queries Level 4 specification includes some syntax improvements to make media queries using features that have a "range" type - for example width or height - less verbose. Level 4 adds a range context for writing such queries.

Range context syntax (simplified range queries)

instead of using min-width/max-width with and, you can now use standard comparison operators like <, >, <=, >=.

using the max- functionality for width we might write the following:

                    @media (max-width: 30em) {
                        /* … */
                    }
                

in media queries level 4 this can be written as:

                    @media (width <= 30em) {
                        /* … */
                    }
                

using min- and max- we might test for a width between two values like so:

                    @media (min-width: 30em) and (max-width: 50em) {
                        /* … */
                    }
                

this would convert to the Level 4 syntax as:

                    @media (30em <= width  <= 50em) {
                        /* … */
                    }
                

level 3

                @media (min-width: 768px) and (max-width: 1023px) { … }
            

level 4

                @media (768px <= width <= 1023px) { … }
            

New media features

prefers-reduced-motion: detects if the user has requested reduced motion (for accessibility).

            @media (prefers-reduced-motion: reduce) {
                * {
                    animation-duration: 0.01ms !important;
                    transition-duration: 0.01ms !important;
                }
            }
        

prefers-color-scheme : detects user preference for light or dark themes.

            @media (prefers-color-scheme: dark) {
                body {
                    background: #121212;
                    color: white;
                }
            }
        

prefers-contrast : indicates user preference for higher or lower contrast. Values: no-preference, less, more, custom.

            @media (prefers-contrast: more) {
                a {
                    outline: 2px solid;
                }
            }
        

prefers-reduced-transparency : for users who prefer less transparency (macOS setting).

            @media (prefers-reduced-transparency) {
                .modal {
                    background: rgba(0,0,0,0.95); /* less transparent */
                }
            }
        

inverted-colors : detects if the OS is inverting colors.

            @media (inverted-colors: inverted) {
                img {
                    filter: invert(1);
                }
            }
        

update, overflow-block, overflow-inline :

update: Indicates how frequently the output device can modify the appearance (none, slow, fast).
overflow-block: How content overflows in the block direction (none, scroll, optional-paged, paged).
overflow-inline: Always scroll for current devices, but future-proofing for non-scrolling inline overflow.

            @media (update: slow) {
                /* Avoid animations on e-Ink displays */
                .spinner { display: none; }
            }
        

Logical operators: "not", "and", "," (OR), and parentheses

Level 4 formalizes and clarifies logical combinations, including better support for "not" at the feature level (not just the whole query).

However, note that full boolean logic (e.g., "not (feature)"" inside a compound query) is still limited — most "not" usage applies to entire media types.

Deprecation of media Types (Except screen, print, speech)

Media Queries Level 4 deprecates most media types (like tty, tv, handheld) in favor of media features, since device capabilities now vary too widely for rigid categories.

You should primarily use:

screen (for screens)
print (for printed documents)
speech (for screen readers)
And rely on features (like width, hover, etc.) to detect capabilities.

Interaction media features

These detect user input capabilities:

pointer: accuracy of primary pointing device (none, coarse, fine)
any-pointer: same, but for any pointer device
hover: whether the primary input can hover (none, on-demand, hover)
any-hover: same, for any device

example:

    @media (hover: hover) and (pointer: fine) {
        button:hover {
            background: #ddd;
        }
    }

Adding breakpoints

top

A breakpoint can be added where certain parts of the design will behave differently on each side of the breakpoint.

Example : when the screen (browser window) gets smaller than 768px, each column should have a width of 100%:

        /* For desktop: */
        .col-1 {width: 8.33%;}
        .col-2 {width: 16.66%;}
        .col-3 {width: 25%;}
        .col-4 {width: 33.33%;}
        .col-5 {width: 41.66%;}
        .col-6 {width: 50%;}
        .col-7 {width: 58.33%;}
        .col-8 {width: 66.66%;}
        .col-9 {width: 75%;}
        .col-10 {width: 83.33%;}
        .col-11 {width: 91.66%;}
        .col-12 {width: 100%;}

        @media only screen and (max-width: 768px) {
            /* For mobile phones: */
            [class*="col-"] {
                width: 100%;
            }
        }
    

Breakpoints are the screen widths at which your website layout should change to provide an optimal viewing experience.
These values act as general guidelines and can be adjusted based on your design needs.

Mobile (small) 0px – 479px : @media (max-width: 479px)
Mobile (large) : 480px – 767px : @media (min-width: 480px) and (max-width: 767px)
Tablet (portrait) : 768px – 899px : @media (min-width: 768px) and (max-width: 899px)
Tablet (landscape) : 900px – 1023px : @media (min-width: 900px) and (max-width: 1023px)
Desktop (small) : 1024px – 1279px : @media (min-width: 1024px) and (max-width: 1279px)
Desktop (medium) : 1280px – 1439px : @media (min-width: 1280px) and (max-width: 1439px)
Desktop (large) : 1440px and above : @media (min-width: 1440px)


Typical device breekpoints

top

There are tons of screens and devices with different heights and widths, so it is hard to create an exact breakpoint for each device. To keep things simple you could target five groups:

        /* Extra small devices (phones, 600px and down) */
        @media only screen and (max-width: 600px) {...}

        /* Small devices (portrait tablets and large phones, 600px and up) */
        @media only screen and (min-width: 600px) {...}

        /* Medium devices (landscape tablets, 768px and up) */
        @media only screen and (min-width: 768px) {...}

        /* Large devices (laptops/desktops, 992px and up) */
        @media only screen and (min-width: 992px) {...}

        /* Extra large devices (large laptops and desktops, 1200px and up) */
        @media only screen and (min-width: 1200px) {...}
    

Default media queries ranges:

phones: up to 480px
landscape phones & smaller portrait tablets: 481px to 768px
landscape tablets & laptops: 769px to 1024px
larger displays: 1025px to 1366px
extra wide monitors and TVs: above 1366px


Media queries examples

top

media queries to change the background color for different viewport widths

the web page will have a lightblue background if the orientation is in landscape mode:

        @media only screen and (orientation: landscape) {
            body {
                background-color: lightblue;
            }
        }
    

for devices with a minimum width of 768px medium)

            @media screen and (min-width: 768px) {
                body {
                    background-color: blue;
                    color: white;
                }
            }
    

for devices with a minimum width of 992px (large)

        @media screen and (min-width: 992px) {
            body {
                background-color: tan;
                color: black;
            }
        }
    

if the screen size is 600px wide or less, hide the element

        @media only screen and (max-width: 600px) {
            div.example {
                display: none;
            }
        }
    

if the screen size is 601px or more, set the font-size of <div> to 80px

        @media only screen and (min-width: 601px) {
            div.example {
                font-size: 80px;
            }
        }
    

if the screen size is 600px or less, set the font-size of <div> to 30px

        @media only screen and (max-width: 600px) {
            div.example {
                font-size: 30px;
            }
        }
    

media queries for columns

    * {box-sizing: border-box; }
    /* Container for flexboxes */
    .container { display: flex; flex-wrap: wrap;}
    /* Create four equal columns */
    .column {flex: 25%; padding: 20px;}
    

on screens that are 992px wide or less, go from four columns to two columns

@media screen and (max-width: 992px) { .column {flex: 50%; } }

On screens that are 600px wide or less, make the columns stack on top of each other instead of next to each other

@media screen and (max-width: 600px) { .container {flex-direction: column;} }

Best practices for writing media queries

top

1. use Mobile-First with "min-width" : start with base styles for mobile and layer on styles for larger devices using min-width. This improves load performance and aligns with modern browsing habits.

2. avoid targeting specific devices : don’t write queries like @media (device-width: 375px). Devices vary widely, so base breakpoints on content layout needs instead of device names.

3. keep breakpoints meaningful : choose breakpoints based on where your design breaks, not arbitrary numbers. Use design-driven breakpoints such as:

 @media (min-width: 640px) { ... } /* small tablets */ 
@media (min-width: 768px) { ... } /* tablets */
@media (min-width: 1024px) { ... } /* desktops */

4. use relative units (em, rem) : instead of pixels, use relative units for breakpoints. This ensures your media queries respond to user zoom and base font settings.

em : recommended for accessibility (respects user's browser font settings). Most style guides (e.g., USWDS) prefer this.

px : predictable, widely used. Safe if accessibility scaling isn't a priority.

        @media (min-width: 48em) {
         /* Scales with user's settings */
        }
    

5. organize media queries logically : group your media queries by component instead of scattering them. You can either: inline queries with components (modular CSS or SCSS) or group them at the bottom, consistently across files.

6. avoid overlapping ranges : ensure there’s no overlap or gap between your breakpoints.

7. test across real devices : always test how your media queries behave on actual devices, not just browser emulators.

8. use logical combinations when needed : combine multiple conditions (for example, width and orientation) for finer control: @media (min-width: 768px) and (orientation: portrait) { ...}

9. avoid too many breakpoints : more breakpoints means harder maintenance. Stick to 3 to 5 well-placed breakpoints based on real layout needs.


Mobile-first vs Desktop-first media queries

top

Mobile-first and desktop-first are two different approaches to structuring responsive CSS using media queries:

Mobile-first : in this approach, you write your base styles for smaller screens (typically mobile devices), and then use "min-width" media queries to progressively enhance the design for larger screens, like tablets and desktops.

example

        /* Base styles for mobile */
        body {font-size: 14px;}
        /* Tablet and up */
        @media (min-width: 768px) {
            body {font-size: 16px;}
        }
        /* Desktop and up */
        @media (min-width: 1024px) {
            body {font-size: 18px;}
        }
    

Best for performance and future-proofing, as it ensures mobile users receive minimal CSS first.

Desktop-first : your base styles target larger screens (desktops), and you use "max-width" media queries to adjust the layout for smaller screens, like tablets and phones.

example

        /* Base styles for desktop */
        body {font-size: 18px;}
        /* Tablet and below */
        @media (max-width: 1024px) {
            body {font-size: 16px;}
        }
        /* Mobile */
        @media (max-width: 767px) {
            body {font-size: 14px;}
        }
    

Media query for desktop

top

Syntax for desktop media query :

        * Base desktop styles */
        @media (max-width: 1024px) {
            /* Adjustments for tablets and below */
        }
    

Common desktop breakpoints :

small desktop : 1024px;
standard desktop : 1280px; large desktop :1440px–1920px

These breakpoints can vary based on your layout or analytics, but 1024px is generally the minimum width for desktop targeting.

Best practices :

use max-width for desktop-first designs: start with styles for larger screens (desktop) and use "max-width" media queries to adjust for tablets and mobile devices.
avoid hardcoding to specific devices: use breakpoints based on content needs, not device names.
test on multiple screen sizes : use real device testing tools to ensure consistency across resolutions.
keep layout fluid : combine media queries with flexible grids and percentage widths for better scaling.
group related rules : keep all desktop-related queries together to maintain clean, maintainable CSS.


Media query for tablet

Media query syntax for tablets :

Mobile-first (using "min-width" and "max-width"):

        @media (min-width: 768px) and (max-width: 1023px) {
           /* Styles for tablets */
           .grid-layout {grid-template-columns: 1fr 1fr;}

        }
    

Desktop-first (using only "max-width"):

        @media (max-width: 1023px) {
          * Adjust layout for tablet and smaller */
            .sidebar {display: none;}
        }
    

Common tablet breakpoints :

small tablet : 600px – 767px
standard tablet : 768px – 1023px

Best practices :

Don’t assume all tablets are used in landscape mode. Also support portrait and landscape orientations.
use min-width + max-width ranges to avoid overlap with mobile or desktop styles.
test on real devices especially for iPads and Android tablets with varying resolutions.